/** * AbstractValueHolder - A partial implementation of a ValueHolder Interface * * Copyright (c) 2002 * Marty Phelan, All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package com.taursys.model; import java.util.Vector; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import com.taursys.util.DataTypes; import com.taursys.util.UnsupportedDataTypeException; import com.taursys.model.event.ContentValueChangeEvent; /** * AbstractValueHolder is a partial implementation of the ValueHolder Interface. * @author Marty Phelan * @version 1.0 */ public abstract class AbstractValueHolder implements ValueHolder { private String alias; private transient Vector changeListeners; private boolean multiplePropertiesChanging; /** * Constructs a new AbstractValueHolder */ public AbstractValueHolder() { } // *********************************************************************** // * PROPERTY VALUE ACCESSOR METHODS // *********************************************************************** /** * Get the java data type for the given propertyName * @return the java data type for the given propertyName */ public abstract int getJavaDataType(String propertyName) throws ModelException; /** * Get the value for the given property name. * @return the value for the given property name. */ public abstract Object getPropertyValue(String propertyName) throws ModelException; /** * Get the values for the given property names. * This method returns an empty Object array if the given propertyNames * is null or empty. * @param propertyNames array of property names * @return the values for the given property names. */ public Object[] getPropertyValues(String[] propertyNames) throws ModelException { if (propertyNames != null && propertyNames.length > 0) { Object[] results = new Object[propertyNames.length]; for (int i = 0; i < propertyNames.length; i++) { results[i] = getPropertyValue(propertyNames[i]); } return results; } else { return new Object[]{}; } } /** * Set the named property's value to the given value. * Fires a StateChanged event to any listeners. * @param propertyName the property to update * @param the value to update the property with */ public abstract void setPropertyValue(String propertyName, Object value) throws ModelException; /** * Set the the named property's values to the given values * This method also sets the multiplePropertiesChanging to true * while it is updating properties. Implementations of setPropertyValue * method should not generate events if this flag is true. * When complete, this method fires a StateChanged event to any listeners. * This method does nothing if either propertyNames or values are null, or * if they are different sizes. * @param propertyNames the names of the properties to update * @values the values to update the properties with */ public void setPropertyValues(String[] propertyNames, Object[] values) throws ModelException { // Precheck for valid conditions checkArrays(propertyNames, values); setMultiplePropertiesChanging(true); try { for (int i = 0; i < propertyNames.length; i++) { setPropertyValue(propertyNames[i], values[i]); } fireStateChanged(new ContentValueChangeEvent(this, null, null, null)); } finally { setMultiplePropertiesChanging(false); } } /** * Check to ensure arrays are not null and same size * @param propertyNames the list of property names * @param values the corresponding values * @throws ModelException.REASON_MULTI_PROPERTY_MISMATCH if either array * is null or they are not the same size. */ protected void checkArrays(String[] propertyNames, Object[] values) throws ModelException { if (propertyNames == null || values == null || propertyNames.length != values.length) throw new ModelException(ModelException.REASON_MULTI_PROPERTY_MISMATCH); } // *********************************************************************** // * GENERAL PROPERTIES // *********************************************************************** /** * Sets the alias name for this VOValueHolder. This property is used by the * ComponentFactory to bind Components to ValueHolders by matching it to the * first part of the Component's ID property. * @param newAlias the alias name for this VOValueHolder */ public void setAlias(String newAlias) { alias = newAlias; } /** * Gets the alias name for this VOValueHolder. This property is used by the * ComponentFactory to bind Components to ValueHolders by matching it to the * first part of the Component's ID property. * @return the alias name for this VOValueHolder */ public String getAlias() { return alias; } /** * Set flag indicating that multiple properties are being changed. * This flag is intended to avoid multiple events from being fired for * a single batch update. * @param multiplePropertiesChanging flag indicating that multiple * properties are being changed. */ protected void setMultiplePropertiesChanging(boolean multiplePropertiesChanging) { this.multiplePropertiesChanging = multiplePropertiesChanging; } /** * Get flag indicating that multiple properties are being changed. * This flag is intended to avoid multiple events from being fired for * a single batch update. * @return flag indicating that multiple properties are being changed. */ protected boolean isMultiplePropertiesChanging() { return multiplePropertiesChanging; } // *********************************************************************** // * CHANGE LISTENER METHODS // *********************************************************************** /** * Removes the specified change listener so that it no longer receives * change events from this value holder. * Change events are generated whenever the contents of the value holder change. */ public synchronized void removeChangeListener(ChangeListener l) { if (changeListeners != null && changeListeners.contains(l)) { Vector v = (Vector) changeListeners.clone(); v.removeElement(l); changeListeners = v; } } /** * Adds the specified change listener to receive change events from this value holder. * Change events are generated whenever the contents of the value holder change. */ public synchronized void addChangeListener(ChangeListener l) { Vector v = changeListeners == null ? new Vector(2) : (Vector) changeListeners.clone(); if (!v.contains(l)) { v.addElement(l); changeListeners = v; } } /** * Reports a state change to all change listeners. */ protected void fireStateChanged(ChangeEvent e) { if (changeListeners != null) { Vector listeners = changeListeners; int count = listeners.size(); for (int i = 0; i < count; i++) { ((ChangeListener) listeners.elementAt(i)).stateChanged(e); } } } }